package com.hnust.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hnust.entity.Device;
import com.hnust.entity.Position;
import com.hnust.entity.code.DeviceCode;
import com.hnust.entity.code.SensorCode;
import com.hnust.entity.dto.DeviceDto;
import com.hnust.entity.dto.DeviceSum;
import com.hnust.entity.dto.PositionDto;
import com.hnust.mapper.DeviceMapper;
import com.hnust.service.DeviceCodeService;
import com.hnust.service.DeviceService;
import com.hnust.service.PositionService;
import com.hnust.service.SensorCodeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 创建人：zhangRuWang
 * 创建时间：2022/5/5
 * 描述：
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {

    @Autowired
    private DeviceCodeService deviceCodeService;
    @Autowired
    private SensorCodeService sensorCodeService;
    @Autowired
    private PositionService positionService;

    @Override
    public DeviceSum deviceSum() {
        DeviceSum d=new DeviceSum();

        QueryWrapper<Device> deviceSensorQuery=new QueryWrapper<>();
        deviceSensorQuery.eq("device_type","传感器");
        d.setSensor(this.count(deviceSensorQuery));

        QueryWrapper<Device> deviceNoControlQuery=new QueryWrapper<>();
        deviceNoControlQuery.eq("device_type","非控制设备");
        d.setNonControlDevice(this.count(deviceNoControlQuery));

        QueryWrapper<Device> deviceControlQuery=new QueryWrapper<>();
        deviceControlQuery.eq("device_type","控制设备");
        d.setControlDevice(this.count(deviceControlQuery));

        QueryWrapper<Device> deviceOnlineQuery=new QueryWrapper<>();
        deviceOnlineQuery.eq("state",1);
        d.setDeviceOnline(this.count(deviceOnlineQuery));

        QueryWrapper<Device> deviceOfflineQuery=new QueryWrapper<>();
        deviceOfflineQuery.eq("state",0);
        d.setDeviceOffline(this.count(deviceOfflineQuery));

        d.setDeviceNum(
                d.getDeviceOnline()+d.getDeviceOffline()
        );
        return d;
    }

    @Override
    public Page<DeviceDto> deviceSearch(int page, int pageSize, String deviceType, String deviceName) {
        Page<Device> devicePage=new Page<>(page,pageSize);
        Page<DeviceDto> deviceDtoPage=new Page<>(page,pageSize);
        //查找设备名对应的设备代码
        //查询device表
        QueryWrapper<Device> deviceQuery=new QueryWrapper<>();
        //添加 device_name 条件
        List<Integer> codes=new ArrayList<>();
        if(deviceType!=null){
            if(deviceType.equals("传感器" +
                    "")){
                //在传感器代码表中找
                QueryWrapper<SensorCode> sensorCodeQuery=new QueryWrapper<>();
                sensorCodeQuery.like(deviceName!=null,"sensor_name",deviceName);
                List<SensorCode> sensorCodes=sensorCodeService.list(sensorCodeQuery);
                //生成传感器码的范围
                for(SensorCode d:sensorCodes){
                    codes.add(d.getCode());
                }
            }else{
                //在设备代码表中找
                QueryWrapper<DeviceCode> deviceCodeQuery=new QueryWrapper<>();
                deviceCodeQuery.like(deviceName!=null,"device_name",deviceName);
                List<DeviceCode> deviceCodes=deviceCodeService.list(deviceCodeQuery);
                //生成设备码的范围
                for(DeviceCode d:deviceCodes){
                    codes.add(d.getCode());
                }
            }
            if(codes.size()==0) {
                codes.add(0);//添加一个不存在的设备码，导致它没有结果
            }
            deviceQuery.in("code",codes);
            //添加 device_type 条件
            deviceQuery.eq("device_type",deviceType);
            //排序
            deviceQuery.orderByDesc("update_time");
        }
        this.page(devicePage,deviceQuery);
        BeanUtils.copyProperties(devicePage,deviceDtoPage,"records");
        List<Device> devices=devicePage.getRecords();
        List<DeviceDto> deviceDtos=devices.stream().map((item)->{
            DeviceDto deviceDto=new DeviceDto();
            this.deviceToDto(deviceDto,item);
            return deviceDto;
        }).collect(Collectors.toList());
        deviceDtoPage.setRecords(deviceDtos);
        return deviceDtoPage;
    }

    /**
     * 将device对象转为dto对象
     * @param deviceDto dto对象
     * @param device dao对象
     */
    public void deviceToDto(DeviceDto deviceDto,Device device){
        BeanUtils.copyProperties(device,deviceDto);
        //获取设备名字
        if(device.getDeviceType().equals("传感器")){
            QueryWrapper<SensorCode> wrapper=new QueryWrapper<>();
            wrapper.eq("code",device.getCode());
            SensorCode sensorCode=sensorCodeService.getOne(wrapper);
            deviceDto.setName(sensorCode.getSensorName());
        }else{
            QueryWrapper<DeviceCode> wrapper=new QueryWrapper<>();
            wrapper.eq("code",device.getCode());
            DeviceCode deviceCode=deviceCodeService.getOne(wrapper);
            deviceDto.setName(deviceCode.getDeviceName());
            //不是传感器还要设置开关名
            deviceDto.setSwitchesName(device.getSwitches()==1?"开":"关");
        }
        //获取状态名
        deviceDto.setStateName(device.getState()==1?"在线":"离线");
        //获取位置
        Position position=positionService.getById(device.getPositionId());
        PositionDto positionDto=new PositionDto();
        positionService.positionToDto(positionDto,position);
        deviceDto.setPositionDto(positionDto);
    }

    @Transactional
    public void deviceAdd(DeviceDto deviceDto) {
        //需要写两张表，最好开启事务
        Position p=new Position();
        BeanUtils.copyProperties(deviceDto.getPositionDto(),p);
        positionService.save(p);
        Device device=new Device();
        BeanUtils.copyProperties(deviceDto,device);
        device.setPositionId(p.getId());
        this.save(device);
    }

    @Transactional
    public void deviceModify(DeviceDto deviceDto) {
        //需要写两张表，最好开启事务
        Position p=new Position();
        BeanUtils.copyProperties(deviceDto.getPositionDto(),p);
        positionService.updateById(p);
        Device device=new Device();
        BeanUtils.copyProperties(deviceDto,device);
        this.updateById(device);
    }
}
